//
// Created by mio on 25-5-12.
//

#ifndef WASAPICAPTURE_H
#define WASAPICAPTURE_H

#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <wrl.h>
#include <cstdio>
#include <cstdint>
#include <functional>
#include <mutex>
#include <memory>
#include <thread>

class WASAPICapture
{
public:
    typedef std::function<void(const WAVEFORMATEX *mixFormat, uint8_t *data, uint32_t samples)> PacketCallback;
    WASAPICapture();
    WASAPICapture(const WASAPICapture&) = delete;
    WASAPICapture& operator=(const WASAPICapture&) = delete;
    ~WASAPICapture();
    int Init();
    int Exit();
    int Start();
    int Stop();
    void SetCallback(PacketCallback callback) { callback_ = callback; }
    WAVEFORMATEX *GetAudioFormat() const { return mixFormat_; }

private:
    int AdjustFormatTo16Bits(WAVEFORMATEX *pwfx);
    int Capture();

private:
    bool initialized_ = false;
    bool isEnabeld_ = false;

    const int REFTIMES_PER_SEC = 10000000;
    const int REFTIMES_PER_MILLISEC = 10000;
    const IID IID_IAudioClient = __uuidof(IAudioClient);
    const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
    const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
    const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);

    std::mutex mtx_;
    uint32_t pcmBufSize_;
    uint32_t bufferFrameCount_;
    PacketCallback callback_;
    WAVEFORMATEX* mixFormat_ = NULL;
    std::shared_ptr<uint8_t> pcmBuf_; // 存放捕获之后的PCM
    REFERENCE_TIME hnsActualDuration_;
    std::shared_ptr<std::thread> threadPtr_;
    Microsoft::WRL::ComPtr<IMMDevice> device_;
    Microsoft::WRL::ComPtr<IAudioClient> audioClient_;
    Microsoft::WRL::ComPtr<IMMDeviceEnumerator> enumerator_;
    Microsoft::WRL::ComPtr<IAudioCaptureClient> audioCaptureClient_;
};

#endif //WASAPICAPTURE_H